#include "stdafx.h"
#include "NodeUtil.h"

#include "Scene.h"
#include "ModelNode.h"
#include "MultiObjectNode.h"
#include "Light.h"

#include "PhysicsSystem.h"
#include "PhysicsPrimitives.h"

#include "RenderingSystem.h"
#include "MeshInstance.h"
#include "Material.h"
#include "EditorRenderStage.h"
#include "Mesh.h"

using namespace mscene;

static void fillNodeData( Node & node, const PrimitiveNodeDesc & desc )
{
	node.Position = desc.Position;
	node.Orientation = desc.Orientation;
	node.Scale = desc.Scale;
	node.IsStatic = desc.IsStatic;
}

PrimitiveNodeDesc::PrimitiveNodeDesc()
{
	Position = XMFLOAT3(0, 0, 0);
	Orientation = XMFLOAT4(0, 0, 0, 1);
	Scale = XMFLOAT3(1, 1, 1);
	IsStatic = false;
	Color = Color::WHITE;
}

ModelNode * mscene::createBoxNode( const PrimitiveNodeDesc & desc, const WorldData & world )
{
	ModelNode * node = new ModelNode(*world.Scene, ModelNode::BOX);
	fillNodeData(*node, desc);

	mgfx::MeshDesc meshDesc;
	meshDesc.FileName = "box.ms3d";
	meshDesc.LoadTextures = false;

	mgfx::MeshInstance * mesh = world.RenderSystem->createMeshInstance(meshDesc);
	mesh->Material_ = mgfx::Material::create();
	mesh->Material_->initDefault();
	mesh->Material_->DiffuseColor = desc.Color;

	node->setModel(*mesh);

	node->setRigidBody(world.PhysicsSystem->createBoxRigidBody());
	node->updateRigidBody();

	world.Scene->addNode(*node);

	return node;
}

ModelNode * mscene::createSphereNode( const PrimitiveNodeDesc & desc, const WorldData & world )
{
	ModelNode * node = new ModelNode(*world.Scene, ModelNode::SPHERE);
	fillNodeData(*node, desc);

	mgfx::MeshDesc meshDesc;
	meshDesc.FileName = "sphere.ms3d";
	meshDesc.LoadTextures = false;

	mgfx::MeshInstance * mesh = world.RenderSystem->createMeshInstance(meshDesc);
	mesh->Material_ = mgfx::Material::create();
	mesh->Material_->initDefault();
	mesh->Material_->DiffuseColor = desc.Color;

	node->setModel(*mesh);

	node->setRigidBody(world.PhysicsSystem->createSphereRigidBody());
	node->updateRigidBody();

	world.Scene->addNode(*node);

	return node;
}

ModelNode * mscene::createPlaneNode( const PrimitiveNodeDesc & desc, const WorldData & world )
{
	ModelNode * node = new ModelNode(*world.Scene, ModelNode::PLANE);
	fillNodeData(*node, desc);

	mgfx::MeshDesc meshDesc;
	meshDesc.FileName = "plane100.3ds";
	meshDesc.GenerateBoundingSphere = true;

	mgfx::MeshInstance * mesh = world.RenderSystem->createMeshInstance(meshDesc);
	mesh->Material_ = mgfx::Material::create();
	mesh->Material_->initDefault();
	mesh->Material_->DiffuseColor = desc.Color;

	node->setModel(*mesh);

	node->setRigidBody(world.PhysicsSystem->createPlaneRigidBody());
	node->updateRigidBody();

	world.Scene->addNode(*node);

	return node;
}

Node * mscene::createPointLightNode( const PrimitiveNodeDesc & desc, const mgfx::PointLightDesc & lightDesc, const WorldData & world )
{
	MultiObjectNode * node = new MultiObjectNode(*world.Scene);
	fillNodeData(*node, desc);
	node->addGfxObject(*(world.RenderSystem->createPointLight(lightDesc)));
	world.Scene->addNode(*node);

	return node;
}

Node * mscene::createSpotLightNode( const PrimitiveNodeDesc & desc, const mgfx::SpotLightDesc & lightDesc, const WorldData & world )
{
	MultiObjectNode * node = new MultiObjectNode(*world.Scene);
	fillNodeData(*node, desc);
	node->addGfxObject(*(world.RenderSystem->createSpotLight(lightDesc)));
	world.Scene->addNode(*node);

	return node;
}

void mscene::fillEditorRenderDataFromNodes( const std::vector<Node*> & nodes, mgfx::EditorRenderData & outData )
{
	for(size_t i = 0; i < nodes.size(); i++)
	{
		if(nodes[i]->Type == Node::MODEL)
		{
			ModelNode * modelNode = (ModelNode*)nodes[i];
			outData.SelectedMeshes.push_back(&modelNode->getModel());
		}

		
		if(nodes[i]->Type == Node::MULTIOBJECT)
		{
			MultiObjectNode * multiKultiNode = (MultiObjectNode*)nodes[i];
			for(uint i = 0; i < multiKultiNode->GfxObjects.size(); i++)
			{
				mgfx::GfxObject * gfxObj = multiKultiNode->GfxObjects[i];

				if(gfxObj->Type == mgfx::GfxObject::POINT_LIGHT)
				{
					outData.SelectedPointLighs.push_back((mgfx::PointLight *)gfxObj);
				}

				if(gfxObj->Type == mgfx::GfxObject::SPOT_LIGHT)
				{
					outData.SelectedSpotLights.push_back((mgfx::SpotLight *)gfxObj);
				}

				if(gfxObj->Type == mgfx::GfxObject::MESH_INSTANCE)
				{
					outData.SelectedMeshes.push_back((mgfx::MeshInstance *)gfxObj);
				}

				if(gfxObj->Type == mgfx::GfxObject::PARTICLE_SYSTEM)
				{
					outData.SelectedPartSystems.push_back((mgfx::ParticleSystem *)gfxObj);
				}
			}
		}
	}
}


